package com.itheima.utils;

import com.alibaba.fastjson.JSONObject;
import com.itheima.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 登录检查过滤器：拦截所有请求并校验登录状态
 */
@Slf4j
@WebFilter(urlPatterns = "/*") // 拦截所有请求
public class LoginCheckFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
            throws IOException, ServletException {
        // 前置：强制转换为 HTTP 协议的请求对象和响应对象
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        // 1. 获取请求 URL
        String url = request.getRequestURL().toString();
        log.info("请求路径：{}", url);

        // 2. 判断请求 URL 中是否包含 "/login"，如果是登录操作，直接放行
        if (url.contains("/login")) {
            log.info("登录操作，放行请求");
            chain.doFilter(request, response);
            return; // 结束当前方法的执行
        }

        // 3. 获取请求头中的令牌（token）
        String token = request.getHeader("token");
        log.info("从请求头中获取的令牌：{}", token);

        // 4. 判断令牌是否存在，如果不存在，返回未登录错误结果
        if (!StringUtils.hasLength(token)) {
            log.info("Token 不存在");
            Result responseResult = Result.error("NOT_LOGIN");
            writeErrorResponse(response, responseResult);
            return;
        }

        // 5. 解析 token，如果解析失败，返回未登录错误结果
        try {
            JwtUtils.parseJwt(token);
            log.info("令牌解析成功");
        } catch (Exception e) {
            log.info("令牌解析失败!");
            Result responseResult = Result.error("NOT_LOGIN");
            writeErrorResponse(response, responseResult);
            return;
        }

        // 6. 放行请求
        chain.doFilter(request, response);
    }

    /**
     * 写入错误响应结果
     *
     * @param response       HTTP 响应对象
     * @param responseResult 错误结果对象
     * @throws IOException 如果写入响应时发生 I/O 异常
     */
    private void writeErrorResponse(HttpServletResponse response, Result responseResult) throws IOException {
        // 将 Result 对象转换为 JSON 格式字符串
        String json = JSONObject.toJSONString(responseResult);
        response.setContentType("application/json;charset=utf-8");
        // 响应错误结果
        response.getWriter().write(json);
    }
}